package com.wn.advice;

import com.wn.annonation.MyLimit;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author yellow Docter
 * @date 2022 -10-28
 * @desc
 *  切面
 */
@Component
@Aspect
@Slf4j
public class MyLimitAdvice {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 编写通知的增强的方法
     *
     *   @Around() 环绕通知：在目标方法的前后可以进行增强
     *
     *   ProceedingJoinPoint 程序的连接点（增强的方法）
     *
     *    @Around(value = "execution( 切点表达式 )")
     *
     *
     * @return
     */
    @Around(value = "execution(* com.wn.service.impl.MemberServiceImpl.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {

        //拿到方法 的签名
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();

        //拿到方法的对象
        Method method = methodSignature.getMethod();

        String name = method.getName();
        log.info("方法的名称:{}",name);

        //从redis 获取访问的次数
        String key =  "limit:" + name;

        String count = stringRedisTemplate.opsForValue().get(key);

        if (Objects.nonNull(count)){ //进行 ++ 操作
            stringRedisTemplate.opsForValue().increment(key);
        }else{
            //第一次 设置访问1次
            stringRedisTemplate.opsForValue().set(key,"1",3, TimeUnit.SECONDS);
        }

        if (method.isAnnotationPresent(MyLimit.class)){
            //拿到限流的数据
            MyLimit myLimit = method.getAnnotation(MyLimit.class);
            int value = myLimit.value();
            if (Objects.nonNull(count) && Integer.parseInt(count)> value ){
                return "亲，请休息一下,不要频繁的访问";
            }
        }
        //执行目标方法
        Object proceed = pjp.proceed();

        return proceed;
    }

}
